#include "Timer.h"

#include <unistd.h>
#include <errno.h>
#include <sys/timerfd.h>
#include <poll.h>
#include <string.h>

#include <iostream>
using namespace std;

Timer::Timer(Callback cb, int initialTime, int intervalTime)
:fd_(createTimerfd())
,cb_(cb)
,initialTime_(initialTime)
,intervalTime_(intervalTime)
{}

int Timer::createTimerfd()
{
    int fd = ::timerfd_create(CLOCK_REALTIME, 0);

    return fd;
}

void Timer::setTimerfd(int initialTime, int intervalTime)
{
    struct itimerspec value;
    memset(&value, 0, sizeof(value));
    value.it_value.tv_sec = initialTime;
    value.it_interval.tv_sec = intervalTime;

    int ret = timerfd_settime(fd_, 0, &value, NULL);

    if (-1 == ret)
    {
        perror("timerfd_settime err");
    }
}

void Timer::start()
{
    struct pollfd pfd;
    pfd.fd = fd_;
    pfd.events = POLLIN;

    setTimerfd(initialTime_, intervalTime_);
    while (1)
    {
        int nready = ::poll(&pfd, 1, -1);
        if (-1 == nready && EINTR == errno)
        {
            continue;
        }
        else if (-1 == nready)
        {
            return;
        }
        else if (nready == 0)
        {
            cout << "poll timeout" << endl;
        }
        else
        {
            if (pfd.fd == fd_ && (pfd.revents & POLLIN))
            {
                handleRead();
                if (cb_)
                {
                    cb_();
                }
            }
        }
    }
}

void Timer::stop()
{}

void Timer::handleRead()
{
    uint64_t howmany;
    int ret = read(fd_, &howmany, sizeof(howmany));
    if (ret != 64)
    {
        cout << "read err" << ret << endl;;
    }
}

void getRand()
{
    ::srand(time(NULL));
    cout << ::rand() % 100 << endl;
}

int main(int argc, char *argv[])
{
    Timer timer(getRand, 1, 3);
    timer.start();
    return 0;
}
